package org.smart4j.plugin.security.realm;

import java.util.HashSet;
import java.util.Set;

import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authz.AuthorizationException;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.subject.SimplePrincipalCollection;
import org.smart4j.framework.util.CollectionUtil;
import org.smart4j.plugin.security.SecurityConstant;
import org.smart4j.plugin.security.SmartSecurity;
import org.smart4j.plugin.security.password.Md5CredentialsMatcher;

/**
 * description: 基于 Smart的自定义Realm （需要实现 SmartSecurity 接口）
 * @version v1.0
 * @author w
 * @date 2018年11月5日下午10:25:52
 **/

public class SmartCustomRealm extends AuthorizingRealm {
	
	private final SmartSecurity smartSecurity;
	
	public SmartCustomRealm(SmartSecurity smartSecurity) {
		this.smartSecurity = smartSecurity;
		super.setName(SecurityConstant.REALMS_CUSTOM);
		super.setCredentialsMatcher(new Md5CredentialsMatcher());
	}
	
	
	/**
	 * 登录验证 
	 */
	@Override
	protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
		if(null == token){
			throw new AuthenticationException("paramter token is null");
		}
		UsernamePasswordToken userToken = (UsernamePasswordToken) token;
		// 获取用户名 
		String username = userToken.getUsername();
		String password = smartSecurity.getPassword(username);
		
		// 将用户名和密码放入 AuthenticationInfo 对象中，便于后续认证操作 
		SimpleAuthenticationInfo simpleAuthenticationInfo = new SimpleAuthenticationInfo();
		// relam 获取的数据和 username 中进行比较
		simpleAuthenticationInfo.setPrincipals(new SimplePrincipalCollection(username, super.getName()));
		simpleAuthenticationInfo.setCredentials(password);
		return simpleAuthenticationInfo;
	}
	
	
	/**
	 * 授权验证 
	 */
	@Override
	protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
		if(null == principals){
			throw new AuthorizationException("paramter principals is null");
		}
		// 获取已认证的用户名 
		String username = (String)super.getAvailablePrincipal(principals);
		
		// 通过SmartSecurity 接口，获取用户名和角色名的集合 
		Set<String> roleNameSet = smartSecurity.getRoleNameSet(username);
		
		Set<String> permissionNameSetAll = new HashSet<String>();
		
		// 通过SmartSecurity 接口，获取角色名和对应权限的集合
		if(CollectionUtil.isNotEmpty(roleNameSet)){
			for (String roleName : roleNameSet) {
				Set<String> permissionNameSet = smartSecurity.getPermissionNameSet(roleName);
				permissionNameSetAll.addAll(permissionNameSet);
			}
		}
		
		// 将角色名集合 与 权限集合 放入AuthorizationInfo 对象中，便于后续的授权操作
		SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
		authorizationInfo.setRoles(roleNameSet);
		authorizationInfo.setStringPermissions(permissionNameSetAll);
		
		return authorizationInfo;
	}

	

}
